home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / dpmi.asm < prev    next >
Encoding:
Assembly Source File  |  1994-08-02  |  23.7 KB  |  1,020 lines

  1. ; original Copyright(C) 1992 Hiroya Tsubakimoto
  2. ; modifications Copyright(C) 1993 Charles Sandmann
  3. ; Merged with GO32 V1.09+ C. Sandmann sandmann@clio.rice.edu
  4. ; Distributed under terms of "copying.dj" when distributed with GO32 source
  5. ; Distributed under terms of GPL if used in any other code
  6.  
  7.     .386p
  8.     include    segdefs.inc
  9.     include    tss.inc
  10.  
  11. ;*--------------------------------------------------------------*
  12. ;DGROUP group _TEXT,_DATA,_BSS  ;(tiny model only)
  13.  
  14. DPMIinfo    struc
  15. vers        db    ?,?
  16. flags        dw    ?
  17. cpu        dw    ?
  18. PIC        db    ?,?
  19. DPMIinfo    ends
  20.  
  21. DPMImemory    struc
  22. address        dd    ?
  23. bytes        dd    ?
  24. handle        dd    ?
  25. DPMImemory    ends
  26.  
  27. regs    struc
  28. rDI    dw    ?,?
  29. rSI    dw    ?,?
  30. rBP    dw    ?,?
  31.     dd    0
  32. rBX    dw    ?,?
  33. rDX    dw    ?,?
  34. rCX    dw    ?,?
  35. rAX    dw    ?,?
  36. rFlags    dw    ?
  37. rES    dw    ?
  38. rDS    dw    ?
  39. rFS    dw    ?
  40. rGS    dw    ?
  41. rIP    dw    ?
  42. rCS    dw    ?
  43. rSP    dw    ?
  44. rSS    dw    ?
  45. regs    ends
  46.  
  47. ;*--------------------------------------------------------------*
  48.     start_data16
  49.  
  50.     extrn    _tss_ptr:word
  51.     extrn    _screen_seg:word
  52.     extrn    _topline_info:word
  53.  
  54. goProtectMode    dd    ?        ;Location of far call routine
  55. realRegs    regs    <>
  56. selfSP        dw    ?
  57. selfSS        dw    ?
  58. ss_lim        dd    0
  59. realSP        dw    ?        ;***stackswap
  60. forced        db    0
  61.  
  62. maxmem_buffer    dw    24 dup(?)
  63.  
  64.     end_data16
  65. ;*--------------------------------------------------------------*
  66.     start_code16
  67.  
  68.     assume    cs:_TEXT,ds:DGROUP
  69.  
  70. numberException    equ    16        ;Number we ever want to handle
  71. selfDS        dw    ?        ;Protected mode 16bit selector to real
  72.  
  73. ;*--------------------------------------------------------------*
  74. ;*    DPMI
  75. ;* Syntax:
  76. ;*    int initDPMI(DPMIinfo* info)
  77. ;* Argument(s):
  78. ;*    "info" DPMI host
  79. ;* Result(s):
  80. ;*    DPMI
  81. ;*     1  0
  82. ;*--------------------------------------------------------------*
  83.     public    _initDPMI
  84. _initDPMI    proc near
  85.     push    bp
  86.     mov    bp,sp
  87.     push    si
  88.     push    di
  89.     mov    realRegs.rCS,cs    ;Remember segment registers
  90.     mov    realRegs.rDS,ds
  91.     mov    realRegs.rSS,ss
  92.  
  93.     mov    ax,1687h    ; Detect DPMI and get Real to Prot Mode Entry
  94.     int    2fh
  95.     and    ax,ax        ; DPMI successful?  AX == 0 means yes
  96.     jnz    @@failed_initDPMI
  97.     test    bx,1        ; 32Bit programs supported has "1" in bit 0
  98.     jz    @@failed_initDPMI
  99.     mov    word ptr goProtectMode[0],di
  100.     mov    word ptr goProtectMode[2],es
  101.     mov    bx,si        ; number of paragraphs required DPMI host data
  102.     mov    ah,48h
  103.     int    21h
  104.     jc    @@failed_initDPMI
  105.     mov    es,ax        ; Real mode segment of DPMI host data area
  106.     mov    ax,1        ; We want a 32Bit application
  107.     call    goProtectMode
  108.     jc    short @@failed_initDPMI
  109.  
  110.     mov    bx,cs            ;Protected mode cs
  111.     mov    ax,000Ah        ;Create alias descriptor we can write
  112.     int    31h
  113.     jc    short @@failed_initDPMI
  114.     mov    es,ax            ;Alias for our code segment
  115.     assume    es:_TEXT
  116.     mov    es:selfDS,ds        ;In protected mode can't write cs!
  117.     assume    es:nothing
  118.     mov    bx,ax            ;Alias for code segment not needed
  119.     mov    ax,0001h        ;Free LDT descriptor
  120.     int    31h
  121.     mov    selfSS,ss        ;Save protected mode ss selector
  122.  
  123.     mov    ax,0400h        ; get DPMI version and flags
  124.     int    31h
  125.     mov    di,word ptr [bp][4]    ; "info"
  126.     mov    word ptr [di].vers,ax
  127.     mov    [di].flags,bx
  128.     xor    ch,ch
  129.     mov    [di].cpu,cx
  130.     mov    word ptr [di].PIC,dx
  131.  
  132.     mov    ax,0900h        ;Disable virtual interrupt
  133.     int    31h
  134.     mov    ax,1
  135.     jmp    short @@done_initDPMI
  136. @@failed_initDPMI:
  137.     xor    ax,ax
  138. @@done_initDPMI:
  139.     xor    ebp,ebp
  140.     pop    di
  141.     pop    si
  142.     pop    bp
  143.     ret
  144. _initDPMI    endp
  145.  
  146.  
  147. ;*--------------------------------------------------------------*
  148. ;* Syntax:
  149. ;*    void uninitDPMI(int retcode)
  150. ;* Argument(s):
  151. ;*    "retcode" exit()
  152. ;*--------------------------------------------------------------*
  153.     public    _uninitDPMI
  154. _uninitDPMI    proc    near
  155.     push    bp
  156.     mov    bp,sp
  157.     mov    ax,0901h        ; Enable virtual interrupts
  158.     int    31h
  159.     mov    ax,word ptr [bp][4]    ; "retcode"
  160.     mov    ah,4ch            ; Terminate program & prot mode
  161.     int    21h
  162. _uninitDPMI    endp
  163.  
  164. ;*--------------------------------------------------------------*
  165. ;* Syntax:
  166. ;*    void DPMIrealMode(void)
  167. ;*--------------------------------------------------------------*
  168.     public    _DPMIrealMode
  169. _DPMIrealMode    proc    near
  170.     pop    bx        ;Where to return from this procedure
  171.     mov    realRegs.rBX,bx
  172.     mov    realRegs.rSI,si
  173.     mov    realRegs.rDI,di
  174.     mov    realRegs.rBP,bp
  175.     mov    realRegs.rSP,sp
  176.     mov    realRegs.rIP,offset _TEXT:@@realModeEntry
  177.     mov    realRegs.rFlags,0202h
  178.     mov    bx,_tss_ptr            ;***stackswap
  179.     lea    sp,[bx].tss_stack        ;***stackswap
  180.     xor    bx,bx        ;No reset of controllers or A20 line
  181.     xor    cx,cx        ;Don't copy any words from prot stack 
  182.     push    ds
  183.     pop    es        ;ES:EDI = Selector:Offset Real mode call struct
  184.     mov    edi,offset DGROUP:realRegs
  185.     mov    ax,0301h    ; far call to real mode procedure
  186.     int    31h
  187.     mov    si,realRegs.rSI    ; We have returned via DPMIprotectedMode
  188.     mov    di,realRegs.rDI
  189.     movzx    ebp,realRegs.rBP
  190.     movzx    esp,realSP            ;***stackswap
  191.     jmp    realRegs.rBX    ; stored by DPMIprotectedMode() below
  192. @@realModeEntry:
  193.     pop    goProtectMode    ; Address to return from real mode callback
  194.  
  195.     cmp    _topline_info,0
  196.     je    no_topline1
  197.     push    es
  198.     push    ax
  199.     mov    ax,_screen_seg
  200.     mov    es,ax
  201.     mov    word ptr es:[0], 0b00h+'R'
  202.     mov    word ptr es:[2], 0b00h+' '
  203.     pop    ax
  204.     pop    es
  205. no_topline1:
  206.     push    bx        ; Address stored in realRegs above
  207.     ret            ; DPMIrealMode()
  208. _DPMIrealMode    endp
  209.  
  210. ;*--------------------------------------------------------------*
  211. ;* Syntax:
  212. ;*    void DPMIprotectedMode(void)
  213. ;*--------------------------------------------------------------*
  214.     public    _DPMIprotectedMode
  215. _DPMIprotectedMode    proc    near
  216.     cmp    _topline_info,0
  217.     je    no_topline2
  218.     push    ax
  219.     push    es
  220.     mov    ax,_screen_seg
  221.     mov    es,ax
  222.     mov    word ptr es:[2], 0b00h+'P'
  223.     mov    word ptr es:[0], 0b00h+' '
  224.     pop    es
  225.     pop    ax
  226. no_topline2:
  227.     pop    bx            ;Return point (will be used in
  228.     mov    realRegs.rBX,bx        ;  DPMIrealMode above)
  229.     mov    realRegs.rSI,si
  230.     mov    realRegs.rDI,di
  231.     mov    realRegs.rBP,bp
  232.     mov    realSP,sp        ;***stackswap
  233.     jmp    goProtectMode    ;Saved retf address from real mode callback
  234. _DPMIprotectedMode    endp
  235.  
  236. ;*--------------------------------------------------------------*
  237. ;* Syntax:
  238. ;*    void DPMIexecute(void)
  239. ;* Note(s):
  240. ;*    We will return from this call in handlerCommon
  241. ;*--------------------------------------------------------------*
  242.     public    _DPMIexecute
  243. _DPMIexecute    proc    near
  244.     push    bp            ; These 3 registers pushed here are
  245.     push    si            ; popped in handlerCommon_done
  246.     push    di
  247.  
  248.     mov    selfSP,sp
  249.     call    _DPMIprotectedMode    ; Switch to 16 bit protected mode
  250.     mov    bx,_tss_ptr
  251.     mov    ss,[bx].tss_ss
  252.     mov    esp,[bx].tss_esp
  253.     push    [bx].tss_eflags        ; Flags to load (by iretd below)
  254.     push    dword ptr [bx].tss_cs    ; CS to execute (32 bit)
  255.     push    [bx].tss_eip        ; EIP to execute (32 bit)
  256.     mov    eax,[bx].tss_eax
  257.     mov    ecx,[bx].tss_ebx
  258.     push    ecx
  259.     mov    ecx,[bx].tss_ecx
  260.     mov    edx,[bx].tss_edx
  261.     mov    ebp,[bx].tss_ebp
  262.     mov    esi,[bx].tss_esi
  263.     mov    edi,[bx].tss_edi
  264.     mov    es,[bx].tss_es
  265.     mov    fs,[bx].tss_fs
  266.     mov    gs,[bx].tss_gs
  267.     mov    ds,[bx].tss_ds
  268.     pop    ebx
  269.  
  270.     push    eax
  271.     mov    ax,0901h        ; Enable virtual interrupts
  272.     int    31h
  273.     pop    eax
  274.  
  275.     iretd                ; Jump to values pushed on stack
  276. _DPMIexecute    endp
  277.  
  278. ;*--------------------------------------------------------------*
  279. ;*
  280. ;* Syntax:
  281. ;*    word32 DPMImaxmem()
  282. ;* Result(s):
  283. ;*     returns number of bytes of memory left
  284. ;*--------------------------------------------------------------*
  285.     public    _DPMImaxmem
  286. _DPMImaxmem    proc    near
  287.     push    bp
  288.     mov    bp,sp
  289.     push    si
  290.     push    di
  291.     mov    ax,0500h            ; Get Free Memory Information
  292.     mov    di, offset maxmem_buffer
  293.     int    31h
  294.     mov    di,[bp+4]
  295.     mov    si,offset maxmem_buffer
  296.     movsd
  297.     add    si,16
  298.     movsd
  299.     add    si,8
  300.     movsd
  301.     pop    di
  302.     pop    si
  303.     pop    bp
  304.     ret
  305. _DPMImaxmem    endp
  306.  
  307. ;*--------------------------------------------------------------*
  308. ;*
  309. ;* Syntax:
  310. ;*    int DPMIalloc(DPMImemory* mem, word32 bytes)
  311. ;* Argument(s):
  312. ;*    "mem"
  313. ;*    "bytes"
  314. ;* Result(s):
  315. ;*     returns 1 or 0 to flag success or failure
  316. ;*     "mem"
  317. ;* Note(s):
  318. ;*    DPMIfree() will release the memory
  319. ;*--------------------------------------------------------------*
  320.     public    _DPMIalloc
  321. _DPMIalloc    proc    near
  322.     push    bp
  323.     mov    bp,sp
  324.     push    si
  325.     push    di
  326.     mov    ax,0501h            ; Allocate memory block
  327. alloc_common:
  328.     mov    cx,word ptr [bp][4+2][0]    ; "bytes" to allocate
  329.     mov    bx,word ptr [bp][4+2][2]
  330.     int    31h                ; returns BX:CX SI:DI
  331.     jc    short @@failed_DPMIalloc
  332.     push    bx                ; save til later
  333.     mov    bx,word ptr [bp][4]        ; "mem" address
  334.     mov    word ptr [bx].handle[0],di
  335.     mov    word ptr [bx].handle[2],si
  336.     mov    word ptr [bx].address[0],cx
  337.     pop    ax
  338.     mov    word ptr [bx].address[2],ax
  339.     mov    ecx,dword ptr [bp][4+2]        ; copy "bytes" into struct
  340.     mov    [bx].bytes,ecx
  341.     mov    ax,1                ; success
  342.     jmp    short @@done_DPMIalloc
  343. @@failed_DPMIalloc:
  344.     xor    ax,ax                ; failure
  345. @@done_DPMIalloc:
  346.     pop    di
  347.     pop    si
  348.     pop    bp
  349.     ret
  350. _DPMIalloc    endp
  351.  
  352. ;*--------------------------------------------------------------*
  353. ;*
  354. ;* Syntax:
  355. ;*    int DPMIrealloc(DPMImemory* mem, word32 bytes)
  356. ;* Argument(s):
  357. ;*    "mem"
  358. ;*    "bytes"
  359. ;* Result(s):
  360. ;*     returns 1 or 0 to flag success or failure
  361. ;*     "mem"
  362. ;* Note(s):
  363. ;*    DPMIfree() will release the memory
  364. ;*--------------------------------------------------------------*
  365.     public    _DPMIrealloc
  366. _DPMIrealloc    proc    near
  367.     push    bp
  368.     mov    bp,sp
  369.     push    si
  370.     push    di
  371.     mov    bx,word ptr [bp][4]        ; "mem" address
  372.     mov    di,word ptr [bx].handle[0]
  373.     mov    si,word ptr [bx].handle[2]
  374.     mov    ax,0503h            ; Resize memory block
  375.     jmp    short alloc_common
  376. _DPMIrealloc    endp
  377.  
  378. ;*--------------------------------------------------------------*
  379. ;*
  380. ;* Syntax:
  381. ;*    void DPMIfree(DPMImemory* mem)
  382. ;* Argument(s):
  383. ;*    "mem"
  384. ;* Note(s):
  385. ;*    DPMIalloc(), DPMIrealloc() allocate the memory block
  386. ;*--------------------------------------------------------------*
  387.     public    _DPMIfree
  388. _DPMIfree    proc    near
  389.     push    bp
  390.     mov    bp,sp
  391.     push    si
  392.     push    di
  393.     mov    bx,word ptr [bp][4]        ; "mem" address
  394.     mov    di,word ptr [bx].handle[0]
  395.     mov    si,word ptr [bx].handle[2]
  396.     mov    ax,0502h            ; Free memory block
  397.     int    31h
  398.     pop    di
  399.     pop    si
  400.     pop    bp
  401.     ret
  402. _DPMIfree    endp
  403.  
  404. ;*--------------------------------------------------------------*
  405. ;*
  406. ;* Syntax:
  407. ;*    word16 DPMIselector(word16 number)
  408. ;* Argument(s):
  409. ;*    "number"
  410. ;* Result(s):
  411. ;*    base value of contiguous LDT desciptors
  412. ;*--------------------------------------------------------------*
  413.     public    _DPMIselector
  414. _DPMIselector    proc    near
  415.     push    bp
  416.     mov    bp,sp
  417.     mov    cx,word ptr [bp][4]        ;"number" to allocate
  418.     mov    ax,0000h            ; Allocate LDT Descriptors
  419.     int    31h                ; returns AX
  420.     jnc    short @@done_DPMIselector
  421.     xor    ax,ax
  422. @@done_DPMIselector:
  423.     pop    bp
  424.     ret
  425. _DPMIselector    endp
  426.  
  427. ;*--------------------------------------------------------------*
  428. ;*
  429. ;* Syntax:
  430. ;*    void DPMIassignSelector(word16 selector, word16 type, word32 base, word32 limit)
  431. ;* Argument(s):
  432. ;*    "selector"
  433. ;*    "type"
  434. ;*    "base"
  435. ;*    "limit"
  436. ;*--------------------------------------------------------------*
  437.     public    _DPMIassignSelector
  438. _DPMIassignSelector    proc    near
  439.     push    bp
  440.     mov    bp,sp
  441.     mov    bx,word ptr [bp][4]        ; "selector"
  442.     mov    dx,word ptr [bp][4+2+2][0]
  443.     mov    cx,word ptr [bp][4+2+2][2]    ; "base"
  444.     mov    ax,0007h            ; Set segment base
  445.     int    31h
  446.     jc    short @@err_DPMIassignSelector
  447.  
  448.     lar    ax,bx                ; get priv level of selector bx
  449.     and    ah,60h                ; Mask all except CPL
  450.     mov    cx,word ptr [bp][4+2]        ; "type"
  451.     and    cl,9fh                ; Clear passed CPL
  452.     or    cl,ah                ; Insert CPL of selector
  453.     mov    ax,0009h            ; Set descriptor access rights
  454.     int    31h
  455.     jc    short @@err_DPMIassignSelector
  456.  
  457.     mov    dx,word ptr [bp][4+2+2+4][0]
  458.     mov    cx,word ptr [bp][4+2+2+4][2]    ; "limit"
  459.     mov    ax,0008h            ; Set segment limit
  460.  
  461. selector_common:
  462.     int    31h
  463.     jc    short @@err_DPMIassignSelector
  464.  
  465.     mov    ax,1
  466.     jmp    short @@done_DPMIassignSelector
  467. @@err_DPMIassignSelector:
  468.     xor    ax,ax
  469. @@done_DPMIassignSelector:
  470.     pop    bp
  471.     ret
  472. _DPMIassignSelector    endp
  473.  
  474. ;*--------------------------------------------------------------*
  475. ;*
  476. ;* Syntax:
  477. ;*    void DPMISelectorBase(word16 selector, word32 base)
  478. ;* Argument(s):
  479. ;*    "selector"
  480. ;*    "base"
  481. ;*--------------------------------------------------------------*
  482.     public    _DPMISelectorBase
  483. _DPMISelectorBase    proc    near
  484.     push    bp
  485.     mov    bp,sp
  486.     mov    bx,word ptr [bp][4]        ; "selector"
  487.     mov    dx,word ptr [bp][4+2][0]
  488.     mov    cx,word ptr [bp][4+2][2]    ; "base"
  489.     mov    ax,0007h            ; Set segment base
  490.     jmp    short selector_common
  491. _DPMISelectorBase    endp
  492.  
  493. ;*--------------------------------------------------------------*
  494. ;*
  495. ;* Syntax:
  496. ;*    void DPMIchangeException(word8 no, DPMIaddress* handler)
  497. ;* Argument(s):
  498. ;*    "no"
  499. ;*    "handler"
  500. ;*--------------------------------------------------------------*
  501.     public    _DPMIchangeException
  502. _DPMIchangeException    proc    near
  503.     push    bp
  504.     mov    bp,sp
  505.     mov    ax,0202h        ; Get exception handler vector
  506.     mov    bx,word ptr [bp][4]    ; "no"
  507.     int    31h            ; return value in CX:EDX
  508.     mov    ax,0203h        ; Set exception handler vector
  509. change_common:
  510.     push    cx            ; Save it
  511.     push    edx
  512.     mov    bx,word ptr [bp][4+2]    ; "handler" struct address
  513.     mov    edx,dword ptr [bx][0]
  514.     mov    cx,word ptr [bx][4]
  515.     mov    bx,word ptr [bp][4]    ; "no"
  516.     int    31h            ; Do the change!
  517.     mov    bx,word ptr [bp][4+2]    ; "handler" struct address
  518.     pop    edx            ; original "handler" offset
  519.     mov    dword ptr [bx][0],edx
  520.     pop    cx            ; original "handler" segment
  521.     mov    word ptr [bx][4],cx
  522.     pop    bp
  523.     ret
  524. _DPMIchangeException    endp
  525.  
  526. ;*--------------------------------------------------------------*
  527. ;*
  528. ;* Syntax:
  529. ;*    void DPMIchangeInterrupt(word8 no, DPMIaddress* handler)
  530. ;* Argument(s):
  531. ;*    "no"
  532. ;*    "handler"
  533. ;*--------------------------------------------------------------*
  534.     public    _DPMIchangeInterrupt
  535. _DPMIchangeInterrupt    proc    near
  536.     push    bp
  537.     mov    bp,sp
  538.     mov    ax,0204h        ; Get protected mode interrupt vector
  539.     mov    bx,word ptr [bp][4]    ; "no"
  540.     int    31h            ; return value in CX:EDX
  541.     mov    ax,0205h        ; Set protected mode interrupt vector
  542.     jmp    short change_common
  543. _DPMIchangeInterrupt    endp
  544.  
  545. ;*--------------------------------------------------------------*
  546. ;*
  547. ;* Syntax:
  548. ;*    void DPMIhandlerNPX(DPMIaddress* handler)
  549. ;* Argument(s):
  550. ;*    "handler"
  551. ;* Notes:
  552. ;*      This returns the handler address "no" for NPX hardware exceptions
  553. ;*--------------------------------------------------------------*
  554.     public    _DPMIhandlerNPX
  555. _DPMIhandlerNPX    proc    near
  556.     push    bp
  557.     mov    bp,sp
  558.     mov    bx,word ptr [bp][4]    ; "handler"
  559.     mov    dword ptr [bx][0],offset _TEXT:i75hdlr
  560.     mov    word ptr [bx][4],cs
  561.     pop    bp
  562.     ret
  563. i75hdlr:
  564.     push    eax
  565.     xor    ax,ax
  566.     out    0f0h,al
  567.     mov    al,20h
  568.     out    0a0h,al
  569.     out    020h,al
  570.     mov    al,75h
  571.     call    causeException
  572.     pop    eax
  573.     sti
  574.     iretd
  575. _DPMIhandlerNPX    endp
  576.  
  577. ; code to disable execution
  578. causeException    proc    near
  579.     push    ebx
  580.     push    cx
  581.     push    dx
  582.     push    ds
  583.     mov    ds,cs:selfDS
  584.     mov    forced,al        ; Indicate a fake exception
  585.     mov    bx,_tss_ptr
  586.     movzx    ebx,[bx].tss_ss
  587.     lsl    eax,ebx
  588.     mov    ss_lim,eax
  589.     xor    cx,0fffh
  590.     mov    dx,0ffffh
  591.     mov    ax,0008h        ;Set segment limit
  592.     int    31h
  593.     pop    ds
  594.     pop    dx
  595.     pop    cx
  596.     pop    ebx
  597.     ret
  598. causeException    endp
  599.  
  600. ;*--------------------------------------------------------------*
  601. ;*
  602. ;* Syntax:
  603. ;*    void DPMIehandler(word8 no, DPMIaddress* handler)
  604. ;* Argument(s):
  605. ;*    "no"
  606. ;*    "handler"
  607. ;* Notes:
  608. ;*      This returns the handler address "no" for exceptions.
  609. ;*--------------------------------------------------------------*
  610.     public    _DPMIehandler
  611. _DPMIehandler    proc    near
  612.     push    bp
  613.     mov    bp,sp
  614.     mov    ax,word ptr [bp][4]    ; "no"
  615.     xor    ah,ah
  616.     mov    dx,sizeOfeHandler
  617.     mul    dx
  618.     add    ax,offset _TEXT:ehandlerTable
  619.     jmp    short gethandleraddr
  620.  
  621. ehandler    macro    n
  622.     push    n
  623.     jmp    short ehandlerCommon
  624.     endm
  625.  
  626. ehandlerTable:
  627.     ehandler    0
  628. sizeOfeHandler    equ    $-offset ehandlerTable
  629.     x = 1
  630.     rept numberException
  631.     ehandler    x
  632.     x = x + 1
  633.     endm
  634. ehandlerCommon:
  635.     jmp    handlerCommon
  636. _DPMIehandler    endp
  637.  
  638. ;*--------------------------------------------------------------*
  639. ;*
  640. ;* Syntax:
  641. ;*    void DPMIhandler(word8 no, DPMIaddress* handler)
  642. ;* Argument(s):
  643. ;*    "no"
  644. ;*    "handler"
  645. ;* Notes:
  646. ;*      This returns the handler address "no" for interrupts.
  647. ;*--------------------------------------------------------------*
  648.     public    _DPMIhandler
  649. _DPMIhandler    proc    near
  650.     push    bp
  651.     mov    bp,sp
  652.     mov    ax,word ptr [bp][4]    ; "no"
  653.     xor    ah,ah
  654.     mov    dx,sizeOfHandler
  655.     mul    dx
  656.     add    ax,offset _TEXT:handlerTable
  657. gethandleraddr:
  658.     mov    bx,word ptr [bp][4+2]    ; "handler"
  659.     mov    word ptr [bx][0],ax
  660.     mov    word ptr [bx][2],dx
  661.     mov    word ptr [bx][4],cs
  662.     pop    bp
  663.     ret
  664.  
  665. handler    macro    n
  666.     push    n
  667.     jmp    handlerCommon
  668.     endm
  669.  
  670. handlerTable:
  671.     handler    256
  672. sizeOfHandler    equ    $-offset handlerTable
  673.     x = 257
  674.     rept 255
  675.     handler    x
  676.     x = x + 1
  677.     endm
  678. _DPMIhandler    endp
  679.  
  680. ;*
  681. ;* Note(s):
  682. ;*    This code is called any time an interrupt or execption occurs in the
  683. ;*    32 bit protected mode code.  The interrupt or exception number is
  684. ;*    pushed on the stack (with the high byte being 1 for interrupt).
  685. ;*    This is the only way code may escape the 32 bit mode entered via
  686. ;*    DPMIexecute().
  687. ;*
  688. handlerCommon    proc    near
  689.     push    ax
  690.     mov    ax,0900h            ;Disable virtual interrupts
  691.     int    31h
  692.     pop    ax
  693.     push    ebx                ;tss access
  694.     push    ds
  695.     mov    ds,cs:selfDS
  696.     mov    bx,_tss_ptr
  697.     pop    word ptr [bx].tss_ds
  698.     pop    [bx].tss_ebx
  699.  
  700.     mov    [bx].tss_es,es
  701.     mov    [bx].tss_fs,fs
  702.     mov    [bx].tss_gs,gs
  703.     mov    [bx].tss_esi,esi
  704.     mov    [bx].tss_edi,edi
  705.     mov    [bx].tss_ebp,ebp
  706.     mov    [bx].tss_edx,edx
  707.     mov    [bx].tss_ecx,ecx
  708.     mov    [bx].tss_eax,eax
  709.     
  710.     pop    ax
  711.     mov    [bx].tss_irqn,al
  712.  
  713.     or    ah,ah
  714.     jnz    @@handlerCommon_interrupt
  715.  
  716. ; Exception only code:
  717.     push    ebp
  718.     mov    ebp,esp
  719.  
  720.     cmp    al,12                ; Stack fault?
  721.     jne    not_forced
  722.     mov    al,forced            ; Did we force this in hw int?
  723.     cmp    al,0
  724.     jz    not_forced
  725.     mov    [bx].tss_irqn,al        ; Real exception
  726.     mov    forced,0            ; Its handled
  727.     call    limitFix            ; Fix the limit
  728.  
  729. not_forced:
  730.  
  731.     mov    eax,dword ptr [ebp][12]
  732.     mov    [bx].tss_error,eax
  733.     mov    eax,dword ptr [ebp][12+4]
  734.     mov    [bx].tss_eip,eax
  735.     mov    ax,word ptr [ebp][12+4+4]
  736.     mov    [bx].tss_cs,ax
  737.  
  738.     mov    eax,dword ptr [ebp][12+4+4+4]
  739.     and     ax,0FEFFh                ; clear trace flag
  740.     or      ax, 0200h                ; set iret flag
  741.     mov    [bx].tss_eflags,eax
  742.     mov     dword ptr [ebp][12+4+4+4],eax        ; put back on dpmi-stack
  743.  
  744.     mov     eax, dword ptr [ebp+28]
  745.     mov     [bx].tss_esp, eax
  746.     mov     ax,word ptr [ebp+32]
  747.     mov     word ptr [bx].tss_ss, ax
  748.  
  749.     mov    dword ptr [ebp][16],offset _TEXT:@@handlerCommon_exception
  750.     mov    word ptr [ebp][16+4],cs            ; Set CS:EIP on stack
  751.  
  752. ; Change to 16 bit stack on return from exception (may be 32bit stack exception)
  753.     movzx   eax,selfSP
  754.     mov     dword ptr [ebp+28],eax              ; set ESP on stack
  755.     mov     ax,selfSS
  756.     mov     word ptr [ebp+32],ax            ; set SS on stack
  757.      
  758.     mov     eax,dword ptr [bx].tss_eax        ; restore regs...
  759.     push    dword ptr [bx].tss_ebx
  760.     push    word ptr [bx].tss_ds
  761.     pop     ds
  762.     pop    ebx
  763.  
  764.     pop    ebp
  765.     db    66h
  766.     retf
  767.  
  768. @@handlerCommon_exception:
  769.     mov    ds,cs:selfDS
  770.     push    0                    ; Indicate exception
  771.     jmp    short @@handlerCommon_done
  772.  
  773. @@handlerCommon_interrupt:
  774.     pop    [bx].tss_eip
  775.     pop    dword ptr [bx].tss_cs
  776.     pop    [bx].tss_eflags
  777.     mov    ds,cs:selfDS
  778.     mov    bx,_tss_ptr
  779.     mov    [bx].tss_ss,ss
  780.     mov    [bx].tss_esp,esp
  781.     mov    ss,selfSS
  782.     movzx    esp,selfSP
  783.     push    1                    ; Indicate interrupt
  784. @@handlerCommon_done:
  785.     xor    ebp,ebp
  786.     call    _DPMIrealMode
  787.     pop    ax
  788.  
  789.     pop    di                ; C needs these registers saved
  790.     pop    si
  791.     pop    bp
  792.     ret                    ; DPMIexecute() return point
  793. handlerCommon    endp
  794.  
  795. ; Code to restore ss limit
  796. limitFix    proc    near
  797.     push    bx
  798.     push    cx
  799.     push    dx
  800. ;    mov    bx,[bx].tss_ss        ;We didn't store it yet, but...
  801.     mov     bx,word ptr [ebp+32]    ;Stack selector 
  802.     mov    dx,word ptr ss_lim
  803.     mov    cx,word ptr ss_lim+2
  804.     mov    ax,0008h        ;Set segment limit
  805.     int    31h
  806.     pop    dx
  807.     pop    cx
  808.     pop    bx
  809.     ret
  810. limitFix    endp
  811.  
  812. ;*--------------------------------------------------------------*
  813. ;* Syntax:
  814. ;*    int DPMIsetBreak(word16 sizetype, word32 addr);
  815. ;* Argument(s):
  816. ;*    "sizetype" contains contents of DX - both size and type of breakpoing
  817. ;*    "addr"     contains 32 bit address of breakpoint
  818. ;*--------------------------------------------------------------*
  819.     public    _DPMIsetBreak
  820. _DPMIsetBreak    proc    near
  821.     push    bp
  822.     mov    bp,sp
  823.     call    _DPMIprotectedMode
  824.     mov    dx,word ptr [bp][4]        ; set size and type
  825.     mov    cx,word ptr [bp][4+2]        ; Move 32 bit "addr" to BX:CX
  826.     mov    bx,word ptr [bp][4+2+2]        ; Move 32 bit "addr" to BX:CX
  827.     mov    ax,0B00h            ; Set debug watch point
  828.     int    31h
  829.     jnc    short @@done_DPMIsetBreak
  830.     mov    bx,-1
  831. @@done_DPMIsetBreak:
  832.     push    bx
  833.     call    _DPMIrealMode
  834.     pop    ax
  835.     pop    bp
  836.     ret
  837. _DPMIsetBreak    endp
  838.  
  839. ;*--------------------------------------------------------------*
  840. ;* Syntax:
  841. ;*    int DPMIcancelBreak(int handle);
  842. ;* Argument(s):
  843. ;*    "handle"  contains handle number to cancel and return state
  844. ;*--------------------------------------------------------------*
  845.     public    _DPMIcancelBreak
  846. _DPMIcancelBreak    proc    near
  847.     push    bp
  848.     mov    bp,sp
  849.     call    _DPMIprotectedMode
  850.     mov    bx,word ptr [bp][4]        ; watchpoint handle
  851.     mov    ax,0B02h            ; Get debug watch point state
  852.     int    31h
  853.     jnc    short @@ok_DPMIcancelBreak
  854.     xor    ax,ax                ;Not active if error
  855. @@ok_DPMIcancelBreak:
  856.     and    ax,1                ;Clear all but low bit
  857.     push    ax                ;Watch point execution state
  858.     mov    ax,0B01h            ;Clear debug watch point state
  859.     int    31h
  860.     call    _DPMIrealMode
  861.     pop    ax
  862.     pop    bp
  863.     ret
  864. _DPMIcancelBreak    endp
  865.  
  866. ;*--------------------------------------------------------------*
  867. ;*
  868. ;* Syntax:
  869. ;*    void Pmemget(word16 sel, word32 off, void* addr, word16 bytes)
  870. ;* Argument(s):
  871. ;*    "sel"
  872. ;*    "off"
  873. ;*    "addr"
  874. ;*    "bytes"
  875. ;*--------------------------------------------------------------*
  876.     public    _Pmemget
  877. _Pmemget    proc    near
  878.     push    bp
  879.     mov    bp,sp
  880.     push    si
  881.     push    di
  882.     call    _DPMIprotectedMode
  883.     push    ds
  884.     push    es
  885.     mov    ax,ds                ; ES = curr DS (16 bit area)
  886.     mov    es,ax
  887.     mov    ds,word ptr [bp][4]        ; Move 32 bit "sel" to DS
  888.     mov    esi,dword ptr [bp][4+2]        ; Move 32 bit "off" to ESI
  889.     movzx    edi,word ptr [bp][4+2+4]    ; 16 bit "addr" (ES:EDI)
  890. move_common:
  891.     cld
  892.     movzx    ecx,word ptr [bp][4+2+4+2]    ; "bytes"
  893.     shr    cx,2                ; Get multiple of 4
  894.     jcxz    short @@little_Pmemmove
  895.     db    67h                ; Use esi, edi (32 bit)
  896.     rep    movsd
  897. @@little_Pmemmove:
  898.     movzx    ecx,word ptr [bp][4+2+4+2]    ; "bytes"
  899.     and    cx,3                ; Get remainder of 4
  900.     jcxz    short @@done_Pmemmove
  901.     db    67h                ; Use esi, edi (32 bit)
  902.     rep    movsb
  903. @@done_Pmemmove:
  904.     pop    es
  905.     pop    ds
  906.     call    _DPMIrealMode
  907.     pop    di
  908.     pop    si
  909.     pop    bp
  910.     ret
  911. _Pmemget    endp
  912.  
  913. ;*--------------------------------------------------------------*
  914. ;*
  915. ;* Syntax:
  916. ;*    void Pmemput(word16 sel, word32 off, const void* addr, word16 bytes)
  917. ;* Argument(s):
  918. ;*    "sel"
  919. ;*    "off"
  920. ;*    "addr"
  921. ;*    "bytes"
  922. ;*--------------------------------------------------------------*
  923.     public    _Pmemput
  924. _Pmemput    proc    near
  925.     push    bp
  926.     mov    bp,sp
  927.     push    si
  928.     push    di
  929.     call    _DPMIprotectedMode
  930.     push    ds                ; Not modified but common pop
  931.     push    es
  932.     mov    es,word ptr [bp][4]        ; move 32 bit "sel" to ES
  933.     mov    edi,dword ptr [bp][4+2]        ; move 32 bit "off" to EDI
  934.     movzx    esi,word ptr [bp][4+2+4]    ; 16 bit "addr" (DS:ESI)
  935.     jmp    short move_common
  936. _Pmemput    endp
  937.  
  938. ;*--------------------------------------------------------------*
  939. ;*
  940. ;* Syntax:
  941. ;*    void Pmemset(word16 sel, word32 off, word8 value, word32 bytes)
  942. ;*    "sel"
  943. ;*    "off"
  944. ;*    "value"
  945. ;*    "bytes"
  946. ;*--------------------------------------------------------------*
  947.     public    _Pmemset
  948. _Pmemset    proc    near
  949.     push    bp
  950.     mov    bp,sp
  951.     push    di
  952.     call    _DPMIprotectedMode
  953.     push    es
  954.     mov    es,word ptr [bp][4]    ; "sel"
  955.     mov    edi,dword ptr [bp][4+2]    ; "off"
  956.     mov    ax,word ptr [bp][4+2+4]    ; "value"
  957.     mov    ah,al
  958.     push    ax
  959.     push    ax
  960.     pop    eax
  961.     cld
  962.     mov    ecx,dword ptr [bp][4+2+4+2]    ; "bytes"
  963.     shr    ecx,2
  964.     jecxz    short @@little_Pmemset
  965.     db    67h        ; edi
  966.     rep    stosd
  967. @@little_Pmemset:
  968.     mov    ecx,dword ptr [bp][4+2+4+2]    ; "bytes"
  969.     and    ecx,3
  970.     jcxz    short @@done_Pmemset
  971.     db    67h        ; edi
  972.     rep    stosb
  973. @@done_Pmemset:
  974.     pop    es
  975.     call    _DPMIrealMode
  976.     pop    di
  977.     pop    bp
  978.     ret
  979. _Pmemset    endp
  980.  
  981. ;*--------------------------------------------------------------*
  982. ;*
  983. ;* Syntax:
  984. ;*    word16 Pmemscan(word16 sel, word32 off, word8 value, word16 bytes)
  985. ;*    "sel"
  986. ;*    "off"
  987. ;*    "value"
  988. ;*    "bytes"
  989. ;*--------------------------------------------------------------*
  990.     public    _Pmemscan
  991. _Pmemscan    proc    near
  992.     push    bp
  993.     mov    bp,sp
  994.     push    di
  995.     call    _DPMIprotectedMode
  996.     push    es
  997.     mov    es,word ptr [bp][4]    ; "sel"
  998.     mov    edi,dword ptr [bp][4+2]    ; "off"
  999.     mov    ax,word ptr [bp][4+2+4]    ; "value"
  1000.     cld
  1001.     movzx    ecx,word ptr [bp][4+2+4+2]    ; "bytes"
  1002.     db    67h        ; edi
  1003.     repne    scasb
  1004.     mov    di,0
  1005.     jne    short @@done_Pmemscan
  1006.     mov    di,word ptr [bp][4+2+4+2]    ; "bytes"
  1007.     sub    di,cx
  1008. @@done_Pmemscan:
  1009.     pop    es
  1010.     call    _DPMIrealMode
  1011.     mov    ax,di
  1012.     pop    di
  1013.     pop    bp
  1014.     ret
  1015. _Pmemscan    endp
  1016.  
  1017.     end_code16
  1018. ;*--------------------------------------------------------------*
  1019.     end
  1020.